package ac.rsync.pojo;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import ac.java.utils.AcFile;
import ac.java.utils.AcFileMd5;
import ac.java.utils.Vaild;

public class AcFsRsync {
	private Map orgMap;
	private String orgPath;
	private String descPath;
	
	public void setOrgPath(String orgPath)
	{
		this.orgPath = orgPath;
	}
	
	public void setDescPath(String descPath)
	{
		this.descPath = descPath;
	}
	
	protected String getOrgPath()
	{
		return this.orgPath;
	}
	
	protected String getDescPath()
	{
		return this.descPath;
	}
	
	protected Map getOrgMap() {
		if(!Vaild.isEmpty(this.orgMap))
		{
			return this.orgMap;
		}

		this.orgMap = AcFile.listMd5Files(this.getOrgPath());
		return this.orgMap;
	}
	
	protected Map getDescMap()
	{
		return AcFile.listMd5Files(this.getDescPath());
	}
	
	public boolean rsync()
	{
		if(this.clearDescPath() && this.rsyncDir())
		{
			return true;
		}
		
		return false;
	}
	
	protected boolean rsyncDir()
	{
		Map fsMap = this.getOrgMap();
		if (Vaild.isEmpty(fsMap)) {
			return true;
		}
		
		// 创建目录结构
		if (fsMap.containsKey("d")) {
			Map dMap = (Map) fsMap.get("d");

			Iterator dIt = dMap.entrySet().iterator();
			while (dIt.hasNext()) {
				Entry entry = (Entry) dIt.next();
				String dPath = (String) entry.getKey();
				
				dPath = this.getFsPath(dPath, true);

				String lDPath = this.getDescPath()	+ System.getProperty("file.separator") + dPath;
				File dFile = new File(lDPath);
				if (!dFile.exists() || !dFile.isDirectory()) {
					if (!dFile.mkdirs()) {
						return false;
					}
				}
			}
		}
		
		if (fsMap.containsKey("f")) {
			Map fMap = (Map) fsMap.get("f");

			Iterator fIt = fMap.entrySet().iterator();
			while (fIt.hasNext()) {
				Entry entry = (Entry) fIt.next();
				String fPath = (String) entry.getKey();
				
				String rfPath = this.getFsPath(fPath, true);

				String lFPath = this.getDescPath()	+ System.getProperty("file.separator") + rfPath;
				
				File lFs = new File(lFPath);
				
				// 文件存在
				if(lFs.exists())
				{
					try {
						String md5FsKey = AcFileMd5.getCheckCode(lFs);
						if (fMap.get(fPath).equals(md5FsKey)) {
							continue;
						}
						else
						{
							AcFile.deleteFile(lFPath);
						}
					} catch (Exception e) {
						return false;
					}
				}
				
				// 复制文件
				AcFile.copy(fPath,lFPath);
				
				// 检验文件
				try {
					String md5FsKey = AcFileMd5.getCheckCode(lFs);
					if(!fMap.get(fPath).equals(md5FsKey))
					{
						return false;
					}
				} catch (Exception e) {
					return false;
				}
				
				System.out.println(lFPath);
			}
		}
		
		return true;
	}
	
	protected boolean clearDescPath() {
		// 源文件
		Map<String, Map> oFs = this.getFsMap(this.getOrgMap(), true);
		//System.out.println(oFs);
		// 本地文件
		Map<String, Map> dFs = this.getFsMap(this.getDescMap(),false);
		//System.out.println(dFs);
		//System.out.println("sFsMap:" + sFsMap);
		
		// 删除多余目录
		if (dFs.containsKey("d")) {
			Map<String, String> dMap = dFs.get("d");
			if (oFs.containsKey("d")) {
				Map<String, String> oMap = oFs.get("d");
				Iterator dIt = dMap.entrySet().iterator();
				while (dIt.hasNext()) {
					Entry entry = (Entry) dIt.next();
					String dPath = (String) entry.getKey();

					if (!oMap.containsKey(dPath)) {
						String localPath = this.getDescPath()	+ System.getProperty("file.separator") + dPath;
						//System.out.println(localPath);
						if (!AcFile.deleteDir(localPath)) {
							return false;
						}
					}
				}
			} else {
				File dirFs = new File(this.getDescPath());
				File dirFss[] = dirFs.listFiles();
				for (int i = 0; i < dirFss.length; i++) {
					if (dirFss[i].isDirectory()) {
						if (!AcFile.deleteDir(dirFss[i])) {
							return false;
						}
					}
				}
			}
		}
		
		// 删除多余文件
		if (dFs.containsKey("f")) {
			Map<String, String> dFMap = dFs.get("f");

			if (oFs.containsKey("f")) {
				Map<String, String> oFMap = oFs.get("f");
				Iterator dFIt = dFMap.entrySet().iterator();
				while (dFIt.hasNext()) {
					Entry entry = (Entry) dFIt.next();
					String fPath = (String) entry.getKey();

					if (!oFMap.containsKey(fPath)) {
						String localPath = this.getDescPath() + System.getProperty("file.separator") + fPath;
						// System.out.println(localPath);
						if (!AcFile.deleteFile(localPath)) {
							return false;
						}
					}
				}
			} else {
				Iterator dFIt = dFMap.entrySet().iterator();
				while (dFIt.hasNext()) {
					Entry entry = (Entry) dFIt.next();
					String fPath = (String) entry.getKey();
					String localPath = this.getDescPath() + System.getProperty("file.separator") + fPath;
					if (!AcFile.deleteFile(localPath)) {
						return false;
					}
				}
			}
		}

		// 较验目录
		return true;
	}
	
	protected Map getFsMap(Map<String, Map> fsMap, boolean isOrg) {
		if (null == fsMap) {
			return null;
		}

		Map<String, Map> rsMap = new HashMap<String, Map>();

		if (fsMap.containsKey("d")) {
			Map dMap = new HashMap<String, String>();

			Iterator dIt = fsMap.get("d").entrySet().iterator();
			while (dIt.hasNext()) {
				Entry entry = (Entry) dIt.next();
				String dPath = (String) entry.getKey();
				dMap.put(this.getFsPath(dPath,isOrg), fsMap.get("d").get(
						dPath));
			}

			rsMap.put("d", dMap);
		}

		if (fsMap.containsKey("f")) {
			Map fMap = new HashMap<String, String>();

			Iterator fIt = fsMap.get("f").entrySet().iterator();
			while (fIt.hasNext()) {
				Entry entry = (Entry) fIt.next();
				String fPath = (String) entry.getKey();
				fMap.put(this.getFsPath(fPath,isOrg), fsMap.get("f").get(
						fPath));
			}

			rsMap.put("f", fMap);
		}

		return rsMap;
	}
	
	protected String getFsPath(String path, boolean isOrg) {
		String rs = path;

		if (isOrg) {
			if (rs.startsWith(this.getOrgPath())) {
				rs = rs.substring(this.getOrgPath().length());
				if (rs.startsWith("\\") || rs.startsWith("/")) {
					rs = rs.substring(1);
				}
			}
		} else {
			if (rs.startsWith(this.getDescPath())) {
				rs = rs.substring(this.getDescPath().length());
				if (rs.startsWith("\\") || rs.startsWith("/")) {
					rs = rs.substring(1);
				}
			}
		}

		rs = rs.replace("\\", System.getProperty("file.separator"));
		rs = rs.replace("/", System.getProperty("file.separator"));

		return rs;
	}
	
	public static void main(String[] args) throws IOException {
		AcFsRsync acRsync = new AcFsRsync();
		acRsync.setOrgPath("D:\\sql");
		acRsync.setDescPath("D:\\local\\sql");
		acRsync.rsync();
	}
}
